package cn.bugstack.domain.strategy.service.rule.tree.factory;

import cn.bugstack.domain.strategy.model.valobj.RuleLogicCheckTypeVO;
import cn.bugstack.domain.strategy.model.valobj.RuleTreeVO;
import cn.bugstack.domain.strategy.service.rule.tree.ILogicTreeNode;
import cn.bugstack.domain.strategy.service.rule.tree.factory.engine.IDecisionTreeEngine;
import cn.bugstack.domain.strategy.service.rule.tree.factory.engine.impl.DecisionTreeEngine;
import lombok.*;
import org.springframework.stereotype.Service;

import java.util.Map;

/**
 * @author Fuzhengwei bugstack.cn @小傅哥
 * @description 规则树工厂
 * 
 * logicTreeNodeGroup 的值是 Spring 框架自动注入的，它包含了所有实现 ILogicTreeNode 接口并使用 @Component 注解的类。
 * 在这个项目中，它主要包含三个实现类：RuleLockLogicTreeNode、RuleStockLogicTreeNode 和 RuleLuckAwardLogicTreeNode。
 * 这种设计使得系统能够在不修改核心代码的情况下扩展决策树的功能 - 只需添加新的实现了 ILogicTreeNode 接口的组件，
 * 它就会自动被纳入决策树的节点集合中。
 * 这是一种典型的依赖注入和组件化设计的应用，提高了系统的可扩展性和灵活性。
 * 
 * ----------------------------------------------------------------------------
 * 工作原理：
 * 
 * 1. Spring 自动装配机制
 * 在 Spring 中，当你在构造函数中声明了一个类型为 Map<String, T> 的参数，其中 T 是一个接口或类，
 * Spring 会自动找到所有实现了该接口的 Bean，并将它们注入到这个 Map 中。在这个 Map 中：
 *      Key: Bean 的名称（通常是 Component 注解中指定的值，或者默认是类名首字母小写）
 *      Value: 对应的 Bean 实例
 * 
 * 2. DefaultTreeFactory 中的注入
 * Spring 在创建 DefaultTreeFactory Bean 时，会自动将所有 ILogicTreeNode 实现类作为 Map 注入到构造函数中。
 * 
 * 3. ILogicTreeNode 的实现类
 * 项目中主要有三个 ILogicTreeNode 的实现类，它们分别是：
 * RuleLockLogicTreeNode（次数锁节点）、RuleStockLogicTreeNode（库存扣减节点）、RuleLuckAwardLogicTreeNode（兜底奖励节点）:
 * 
 * 4. Spring 自动注入过程
 * Spring 容器初始化时，扫描并创建所有带有 @Component、@Service 等注解的 Bean
 * 当创建 DefaultTreeFactory Bean 时，Spring 检测到它的构造函数需要一个 Map<String, ILogicTreeNode> 类型的参数
 * Spring 查找所有实现了 ILogicTreeNode 接口的 Bean
 * Spring 构建一个 Map，其中 key 是这些 Bean 的名称（这里是 "rule_lock"、"rule_stock"、"rule_luck_award"），value 是对应的 Bean 实例
 * Spring 将这个 Map 作为参数传入 DefaultTreeFactory 的构造函数
 * 
 * 5. DecisionTreeEngine 中的使用
 * 在 DefaultTreeFactory 的 openLogicTree 方法中，logicTreeNodeGroup 被传递给 DecisionTreeEngine 的构造函数，
 * 然后DecisionTreeEngine 在运行时通过节点的 ruleKey 在这个映射中查找对应的节点实现。
 * ----------------------------------------------------------------------------
 * 
 * @create 2024-01-27 11:28
 */
@Service
public class DefaultTreeFactory {

    private final Map<String, ILogicTreeNode> logicTreeNodeGroup;

    public DefaultTreeFactory(Map<String, ILogicTreeNode> logicTreeNodeGroup) {
        this.logicTreeNodeGroup = logicTreeNodeGroup;
    }

    public IDecisionTreeEngine openLogicTree(RuleTreeVO ruleTreeVO) {
        return new DecisionTreeEngine(logicTreeNodeGroup, ruleTreeVO);
    }

    /**
     * 决策树个动作实习
     */
    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    public static class TreeActionEntity {
        private RuleLogicCheckTypeVO ruleLogicCheckType;
        private StrategyAwardVO strategyAwardVO;
    }

    @Data
    @Builder
    @AllArgsConstructor
    @NoArgsConstructor
    public static class StrategyAwardVO {
        /** 抽奖奖品ID - 内部流转使用 */
        private Integer awardId;
        /** 抽奖奖品规则 */
        private String awardRuleValue;
    }

}
